home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / once_routine_pool.e < prev    next >
Text File  |  2000-03-25  |  14KB  |  516 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class ONCE_ROUTINE_POOL
  17.    --
  18.    -- Singleton object in charge of runnable once routines.
  19.    -- This singleton is shared via the GLOBALS.`once_routine_pool' once function.
  20.    --
  21.  
  22. inherit GLOBALS;
  23.  
  24. feature {RUN_FEATURE} -- For `compile_to_c' as well as `compile_to_jvm' :
  25.  
  26.    register_procedure(rf: RUN_FEATURE) is
  27.       require
  28.          rf.is_once_procedure
  29.       do
  30.          check
  31.             not procedure_list.has(rf)
  32.          end;
  33.          procedure_list.add_last(rf);
  34.       end;
  35.  
  36.    register_function(rf: RUN_FEATURE) is
  37.       require
  38.          rf.is_once_function
  39.       do
  40.          check
  41.             not function_list.has(rf)
  42.          end;
  43.          function_list.add_last(rf);
  44.       end;
  45.  
  46. feature {GC_HANDLER}
  47.  
  48.    gc_mark_in(c_code: STRING) is
  49.      -- To mark results of once functions because they are part 
  50.      -- of the root.
  51.       local
  52.          i: INTEGER;
  53.          rf: RUN_FEATURE;
  54.          of: ONCE_FUNCTION;
  55.          mem: FIXED_ARRAY[ONCE_FUNCTION];
  56.          rt: TYPE;
  57.          oresult: STRING;
  58.       do
  59.          if function_list.count > 0 then
  60.             from
  61.                i := function_list.upper;
  62.                !!mem.with_capacity(i // 2);
  63.             until
  64.                i < 0
  65.             loop
  66.                rf := function_list.item(i);
  67.                of ?= rf.base_feature;
  68.            check
  69.           of /= Void
  70.            end;
  71.                if not mem.fast_has(of) then
  72.                   if rf.current_type.run_class.at_run_time then
  73.                      mem.add_last(of);
  74.                      rt := rf.result_type;
  75.                      if rt.need_gc_mark_function then
  76.                         oresult := o_result(of);
  77.             gc_handler.mark_for(c_code,oresult,rt.run_class);
  78.                      end;
  79.                   end;
  80.                end;
  81.                i := i - 1;
  82.             end;
  83.          end;
  84.       end;
  85.  
  86. feature {JVM}
  87.  
  88.    fields_count: INTEGER;
  89.  
  90.    jvm_define_fields is
  91.       local
  92.          byte_idx, idx_flag, i: INTEGER;
  93.          rf: RUN_FEATURE;
  94.          bf: E_FEATURE;
  95.          name_list: FIXED_ARRAY[INTEGER];
  96.       do
  97.          !!name_list.with_capacity(fields_count);
  98.          if function_list.count > 0 then
  99.             from
  100.                i := function_list.upper;
  101.                byte_idx := constant_pool.idx_utf8(fz_41);
  102.             until
  103.                i < 0
  104.             loop
  105.                rf := function_list.item(i);
  106.                bf := rf.base_feature;
  107.                idx_flag := idx_name_for_flag(bf);
  108.                if name_list.fast_has(idx_flag) then
  109.                else
  110.                   name_list.add_last(idx_flag);
  111.                   -- ---------- Static field for flag :
  112.                   field_info.add(9,idx_flag,byte_idx);
  113.                   -- ---------- Static field for result :
  114.                   field_info.add(9,
  115.                                  idx_name_for_result(bf),
  116.                                  idx_descriptor(rf.result_type.run_type));
  117.                end;
  118.                i := i - 1;
  119.             end;
  120.          end;
  121.          if procedure_list.count > 0 then
  122.             from
  123.                i := procedure_list.upper;
  124.                byte_idx := constant_pool.idx_utf8(fz_41);
  125.             until
  126.                i < 0
  127.             loop
  128.                rf := procedure_list.item(i);
  129.                bf := rf.base_feature;
  130.                idx_flag := idx_name_for_flag(bf);
  131.                if name_list.fast_has(idx_flag) then
  132.                else
  133.                   name_list.add_last(idx_flag);
  134.                   -- ---------- Static field for flag :
  135.                   field_info.add(9,idx_flag,byte_idx);
  136.                end;
  137.                i := i - 1;
  138.             end;
  139.          end;
  140.       end;
  141.  
  142.    jvm_initialize_fields is
  143.       local
  144.          i: INTEGER;
  145.       do
  146.          if jvm_flag_list.count > 0 then
  147.             from
  148.                i := jvm_flag_list.upper;
  149.             until
  150.                i < 0
  151.             loop
  152.                -- Set once flag :
  153.                code_attribute.opcode_iconst_0;
  154.                code_attribute.opcode_putstatic(jvm_flag_list.item(i),-1);
  155.                i := i - 1;
  156.             end;
  157.          end;
  158.       end;
  159.  
  160. feature {RUN_FEATURE} -- For `compile_to_jvm' only :
  161.  
  162.    idx_fieldref_for_flag(rf: RUN_FEATURE): INTEGER is
  163.       require
  164.          rf.is_once_routine
  165.       local
  166.      cp: CONSTANT_POOL;
  167.       do
  168.      cp := constant_pool;
  169.          Result := cp.idx_fieldref3(jvm_root_class,
  170.                     o_flag(rf.base_feature),
  171.                     fz_41);
  172.       end;
  173.  
  174. feature {NONE} -- For `compile_to_c' as well as `compile_to_jvm' :
  175.  
  176.    idx_fieldref_for_result(rf: RUN_FEATURE): INTEGER is
  177.       require
  178.          rf.is_once_function
  179.       local
  180.      cp: CONSTANT_POOL;
  181.      rt: TYPE;
  182.       do
  183.      cp := constant_pool;
  184.          rt := rf.result_type.run_type;
  185.          Result := cp.idx_fieldref3(jvm_root_class,
  186.                     o_result(rf.base_feature),
  187.                     jvm_descriptor(rt));
  188.       end;
  189.  
  190.    procedure_list: FIXED_ARRAY[RUN_FEATURE] is
  191.      -- Live set of once procedures.
  192.       once
  193.          !!Result.with_capacity(32);
  194.       end;
  195.  
  196.    function_list: FIXED_ARRAY[RUN_FEATURE] is
  197.      -- Live set of once functions.
  198.       once
  199.          !!Result.with_capacity(32);
  200.       end;
  201.  
  202.    o_flag(bf: E_FEATURE): STRING is
  203.      -- Compute the only one corresponding `flag': fBCxxKey used
  204.      -- to check that execution is done.
  205.       require
  206.      bf /= Void
  207.       do
  208.      Result := ".....................";
  209.          Result.clear;
  210.          Result.append("fBC");
  211.          bf.base_class.id.append_in(Result);
  212.          Result.append(bf.first_name.to_key);
  213.      Result := string_aliaser.item(Result);
  214.       ensure
  215.      Result = string_aliaser.item(Result)
  216.       end;
  217.  
  218.    buffer: STRING is 
  219.       once
  220.      !!Result.make(64);
  221.       end;
  222.  
  223.    buffer2: STRING is 
  224.       once
  225.      !!Result.make(64);
  226.       end;
  227.  
  228. feature {ABSTRACT_RESULT,RUN_FEATURE}
  229.  
  230.    o_result(bf: E_FEATURE): STRING is
  231.       require
  232.      bf /= Void
  233.       do
  234.      Result := "................";
  235.          Result.clear;
  236.          Result.append("oBC");
  237.          bf.base_class.id.append_in(Result);
  238.          Result.append(bf.first_name.to_key);
  239.      Result := string_aliaser.item(Result);
  240.       ensure
  241.      Result = string_aliaser.item(Result)
  242.       end;
  243.  
  244.    c_put_o_result(rf: RUN_FEATURE) is
  245.       require
  246.      rf.is_once_function
  247.       do
  248.      cpp.put_string(o_result(rf.base_feature));
  249.       end;
  250.  
  251.    jvm_result_load(rf: RUN_FEATURE) is
  252.       require
  253.      rf.is_once_function
  254.       local
  255.          result_space, idx_result: INTEGER;
  256.       do
  257.          result_space := rf.result_type.jvm_stack_space;
  258.          idx_result := idx_fieldref_for_result(rf);
  259.          code_attribute.opcode_getstatic(idx_result,result_space);
  260.       end;
  261.  
  262.    jvm_result_store(rf: RUN_FEATURE) is
  263.       require
  264.      rf.is_once_function
  265.       local
  266.          result_space, idx_result: INTEGER;
  267.       do
  268.          result_space := rf.result_type.jvm_stack_space;
  269.          idx_result := idx_fieldref_for_result(rf);
  270.          code_attribute.opcode_putstatic(idx_result,- result_space);
  271.       end;
  272.  
  273. feature {C_PRETTY_PRINTER} -- For `compile_to_c' :
  274.  
  275.    c_pre_compute is
  276.      -- Generate C code to pre_compute some functions.
  277.       local
  278.      i: INTEGER;
  279.      memory: FIXED_ARRAY[E_FEATURE];
  280.      rf: RUN_FEATURE;
  281.      bf: E_FEATURE;
  282.       do
  283.      echo.put_string(fz_04);
  284.      echo.put_string(fz_05);
  285.      cpp.put_string(fz_pco_comment);
  286.      from
  287.         i := function_list.upper;
  288.         !!memory.with_capacity(64);
  289.      until
  290.         i < 0
  291.      loop
  292.         rf := function_list.item(i);
  293.         if rf.run_class.at_run_time then
  294.            if rf.is_pre_computable then
  295.           bf := rf.base_feature;
  296.           if not memory.fast_has(bf) then
  297.              memory.add_last(bf);
  298.              echo.put_character('%T');
  299.              echo.put_string(bf.base_class.name.to_string);
  300.              echo.put_character('.');
  301.              echo.put_string(rf.name.to_string);
  302.              echo.put_character('%N');
  303.              c_pre_compute_of(rf,bf);
  304.              cpp.put_string(fz_pco_comment);
  305.           end;
  306.            end;
  307.         end;
  308.         i := i - 1;
  309.      end;
  310.      echo.print_count(fz_04,memory.count);
  311.       end;
  312.    
  313. feature {RUN_FEATURE} -- For `compile_to_c' :
  314.  
  315.    c_define_o_flag(rf: RUN_FEATURE) is
  316.      -- Add the definition/initialization of the corresponding 
  317.      -- `o_flag' if not yet done.
  318.       require
  319.      rf.is_once_routine
  320.       local
  321.      bf: E_FEATURE;
  322.      bcbf: BASE_CLASS;
  323.      flag: STRING;
  324.       do
  325.      bf := rf.base_feature;
  326.      bcbf := bf.base_class;
  327.      flag := o_flag(bf);
  328.      if not bcbf.once_flag(flag) then
  329.         buffer.copy("int ");
  330.         buffer.append(flag);
  331.         cpp.put_extern2(buffer,'0');
  332.      end;
  333.       end;
  334.  
  335.    c_define_o_result(rf: RUN_FEATURE) is
  336.       require
  337.      rf.is_once_function
  338.       local
  339.      bf: E_FEATURE;
  340.      bcbf: BASE_CLASS;
  341.      oresult: STRING;
  342.      rt: TYPE;
  343.       do
  344.      bf := rf.base_feature;
  345.      bcbf := bf.base_class;
  346.      oresult := o_result(bf);
  347.      if not bcbf.once_flag(oresult) then
  348.         buffer.clear;
  349.         buffer.extend('T');
  350.         rt := rf.result_type;
  351.         if rt.is_expanded then
  352.            rt.id.append_in(buffer);
  353.            buffer.extend(' ');
  354.         else
  355.            buffer.extend('0');
  356.            buffer.extend('*');
  357.         end;
  358.         buffer.append(oresult);
  359.         buffer2.clear;
  360.         rt.c_initialize_in(buffer2);
  361.         cpp.put_extern5(buffer,buffer2);
  362.      end;
  363.      end;
  364.  
  365.    c_test_o_flag(rf: RUN_FEATURE) is
  366.       require
  367.      rf.is_once_routine
  368.       local
  369.      flag: STRING;
  370.       do
  371.      flag := o_flag(rf.base_feature);
  372.          cpp.put_string("if(");
  373.          cpp.put_string(flag);
  374.          cpp.put_string("==0){");
  375.          cpp.put_string(flag);
  376.      cpp.put_string("=1;{%N");
  377.       end;
  378.  
  379.    c_return_o_result(rf: RUN_FEATURE) is
  380.       require
  381.      rf.is_once_function
  382.       do
  383.          cpp.put_string("}}%Nreturn ");
  384.          cpp.put_string(o_result(rf.base_feature));
  385.          cpp.put_string(";%N}%N");
  386.       end;
  387.  
  388. feature {NONE} -- For `compile_to_jvm' :
  389.  
  390.    jvm_flag_list: FIXED_ARRAY[INTEGER] is
  391.       once
  392.          !!Result.with_capacity(32);
  393.       end;
  394.  
  395.    idx_descriptor(rt: TYPE): INTEGER is
  396.       require
  397.          rt /= Void
  398.       do
  399.          Result := constant_pool.idx_utf8(jvm_descriptor(rt));
  400.       end
  401.  
  402.    idx_name_for_result(bf: E_FEATURE): INTEGER is
  403.       require
  404.          bf /= Void
  405.       do
  406.          Result := constant_pool.idx_utf8(o_result(bf));
  407.       end
  408.  
  409.    idx_name_for_flag(bf: E_FEATURE): INTEGER is
  410.       require
  411.          bf /= Void
  412.       do
  413.          Result := constant_pool.idx_utf8(o_flag(bf));
  414.       end
  415.  
  416.    jvm_descriptor(rt: TYPE): STRING is
  417.       do
  418.      Result := ".............................";
  419.          Result.clear;
  420.          if rt.is_reference then
  421.             Result.append(jvm_root_descriptor)
  422.          else
  423.             rt.jvm_descriptor_in(Result)
  424.          end;
  425.       end;
  426.  
  427. feature {RUN_FEATURE_6,RUN_FEATURE_11}
  428.  
  429.    is_pre_computable(rf: RUN_FEATURE): BOOLEAN is
  430.       require
  431.      rf.is_once_function
  432.       do
  433.          if frozen_general.fast_has(rf.name.to_string) then
  434.             Result := true;
  435.          elseif rf.arguments = Void and then not rf.use_current then
  436.             if rf.routine_body = Void then
  437.                Result := true;
  438.             elseif not run_control.invariant_check then
  439.                Result := rf.routine_body.is_pre_computable;
  440.             end;
  441.          end;
  442.          if Result then
  443.             if rf.require_assertion /= Void then
  444.                rf.require_assertion.clear_run_feature;
  445.             end;
  446.             if rf.ensure_assertion /= Void then
  447.                rf.ensure_assertion.clear_run_feature;
  448.             end;
  449.          end;
  450.       end;
  451.  
  452. feature {NONE}
  453.  
  454.    c_pre_compute_of(rf: RUN_FEATURE; bf: E_FEATURE) is
  455.       require
  456.      rf.is_once_function;
  457.          rf.is_pre_computable;
  458.          cpp.on_c;
  459.       local
  460.      result_type: TYPE;
  461.      local_vars: LOCAL_VAR_LIST;
  462.       do
  463.          if run_control.require_check then
  464.             if rf.require_assertion /= Void then
  465.                rf.require_assertion.compile_to_c;
  466.             end;
  467.          end;
  468.      --
  469.      result_type := rf.result_type;
  470.          if result_type.expanded_initializer /= Void then 
  471.             c_put_o_result(rf);
  472.         cpp.put_character('=');
  473.         result_type.c_initialize;
  474.             cpp.put_string(fz_00);
  475.          end;
  476.      --
  477.      local_vars := rf.local_vars;
  478.          if local_vars /= Void then
  479.             cpp.put_character('{');
  480.             local_vars.c_declare;
  481.          end;
  482.      --
  483.          if rf.routine_body /= Void then
  484.             rf.routine_body.compile_to_c;
  485.          end;
  486.      --
  487.          if run_control.ensure_check then
  488.             if rf.ensure_assertion /= Void then
  489.                rf.ensure_assertion.compile_to_c;
  490.             end;
  491.          end;
  492.      --
  493.          if local_vars /= Void then
  494.             cpp.put_character('}');
  495.          end;
  496.       end;
  497.  
  498.    frozen_general: ARRAY[STRING] is
  499.       once
  500.          Result := <<as_std_error, as_std_input, as_io, as_std_output>>;
  501.       end;
  502.  
  503.    fz_pco_comment: STRING is "/*PCO*/%N";
  504.  
  505.    singleton_memory: ONCE_ROUTINE_POOL is
  506.       once
  507.      Result := Current;
  508.       end;
  509.  
  510. invariant
  511.  
  512.    is_real_singleton: Current = singleton_memory
  513.  
  514. end -- ONCE_ROUTINE_POOL
  515.  
  516.